/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2010 huliqing, huliqing.cn@gmail.com
 *
 * This file is part of QFaces.
 * QFaces is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * QFaces is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with QFaces.  If not, see <http://www.gnu.org/licenses/>.
 *
 * 这个文件是QFaces的一部分。
 * 您可以单独使用或分发这个文件，但请不要移除这个头部声明信息.
 * QFaces是一个自由软件，您可以自由分发、修改其中的源代码或者重新发布它，
 * 新的任何修改后的重新发布版必须同样在遵守LGPL3或更后续的版本协议下发布.
 * 关于LGPL协议的细则请参考COPYING、COPYING.LESSER文件，
 * 您可以在QFaces的相关目录中获得LGPL协议的副本，
 * 如果没有找到，请连接到 http://www.gnu.org/licenses/ 查看并获取副本。
 *
 * - Author: Huliqing
 * - Contact: huliqing.cn@gmail.com
 * - License: GNU Lesser General Public License (LGPL)
 * - Blog and source code availability: http://www.huliqing.name/
 */

Q.F.UIMiniDataTable = {
	// 客户端ID，引用的组件id,要赋值的组件id,绑定的表达式，组件className, 每页显示数， 最多显示多少页，table标题, 是否自动关闭面板
	init : function(clientId, refFull, forFull, searchExp, componentClass, 
				pageSize, displayPage, strHeaders, autoClose, searchWhenOpen, 
				autoLoad, alwaysShow, border, styleClass, headerClass, rowClasses, 
				columnClasses, rowOnClass, sortFields, ascSrc, descSrc, displayJump, 
				strJump, strRecordTotal, strPageTotal, displayInfo, 
				openButtonId, innerPanelId, contentPanelId, scrollerPanelTopId, 
				scrollerPanelBottomId, scrollerOn, alwaysShowScroller, scrollerClass,
				scrollerInfoClass, scrollerPageClass, scrollerPageCurrentClass, scrollerPageOnClass,
				editColumns, editListener) {
		var miniDataTable = new Q.F.UIMiniDataTable.MiniDataTable(
				clientId, refFull, forFull, searchExp, componentClass, 
				pageSize, displayPage, strHeaders, autoClose, searchWhenOpen, 
				autoLoad, alwaysShow, border, styleClass, headerClass, rowClasses, 
				columnClasses, rowOnClass, sortFields, ascSrc, descSrc, displayJump, 
				strJump, strRecordTotal, strPageTotal, displayInfo, 
				openButtonId, innerPanelId, contentPanelId, scrollerPanelTopId, 
				scrollerPanelBottomId, scrollerOn, alwaysShowScroller, scrollerClass,
				scrollerInfoClass, scrollerPageClass, scrollerPageCurrentClass, scrollerPageOnClass,
				editColumns, editListener);
		Q.F.put(clientId, miniDataTable);
	},
	getMiniDataTable : function(clientId) {
		return Q.F.find(clientId);
	},
	
	// 获取数据，从start记录开始显示
	toSearch : function(clientId, start) {
		this.getMiniDataTable(clientId).toSearch(start);
	},
	// 获取数据，从page页开始显示
	toSearchByPage : function(clientId, pageIndex) {
		this.getMiniDataTable(clientId).toSearchByPage(pageIndex);
	}
}

Q.F.UIMiniDataTable.Parse = {
	// 分析分页信息
	parseToTotal : function(xmlResponse) {
		var root = xmlResponse.documentElement;
		var nodeGlobal = root.getElementsByTagName("global")[0];
		return nodeGlobal.getAttribute("total");
	},
	// 将返回的xml数据处理为二维数组
	parseToDataArrs : function(xmlResponse) {
		var dataArrs = new Array();
		var root = xmlResponse.documentElement;
		var nodeValues = root.getElementsByTagName("values")[0].getElementsByTagName("value");
		if (nodeValues == null || nodeValues.length <= 0) {return;}
		for (var i = 0; i < nodeValues.length; i++) {
			var nodeVals = nodeValues[i].getElementsByTagName("val");
			var record = new Array();
			dataArrs[i] = record;
			for (var n = 0; n < nodeVals.length; n++) {
				var fieldVal = nodeVals[n].getAttribute("value");
				record[n] = fieldVal;
			}
		}
		return dataArrs;
	}
}

Q.F.UIMiniDataTable.MiniDataTable = function(clientId, refFull, forFull, searchExp, componentClass,
		pageSize, displayPage, strHeaders, autoClose, searchWhenOpen, 
		autoLoad, alwaysShow, border, styleClass, headerClass, rowClasses, 
		columnClasses, rowOnClass, sortFields, ascSrc, descSrc, displayJump, 
		strJump, strRecordTotal, strPageTotal, displayInfo, 
		openButtonId, innerPanelId, contentPanelId, scrollerPanelTopId, 
		scrollerPanelBottomId, scrollerOn, alwaysShowScroller, scrollerClass,
		scrollerInfoClass, scrollerPageClass, scrollerPageCurrentClass, scrollerPageOnClass,
		editColumns, editListener) {
	this.clientId = clientId;
	this.refFull = refFull; // 引用的客户端组件值的所有id（由“，”分隔）
	this.forFull = forFull; // 要赋值的目标组件的所有id（由“，”分隔）
	this.searchExp = searchExp; // el expression string
	this.componentClass = componentClass;
	this.strHeaders = ((strHeaders != null && strHeaders != "") ? strHeaders : null);
	this.autoClose = (autoClose == "true");
	this.searchWhenOpen = (searchWhenOpen == "true"); // 第一次打开时搜索。
	this.refArr = null;
	this.forArr = null;	// 要赋值的目标组件的id数组
	this.openButton = Q.get(openButtonId);
	this.innerPanel = Q.get(innerPanelId);;					// 主面板区域（包含contentPanel, scrollerPanel）
	this.contentPanel = Q.get(contentPanelId);;				// 数据记录的主区域
	this.scrollerPanelTop = Q.get(scrollerPanelTopId);; 		// 翻页条上部
	this.scrollerPanelBottom = Q.get(scrollerPanelBottomId);;	// 翻页条下部
	this.global;		// MiniDataTable的分页信息Q.F.UIMiniDataTable.Global
	this.autoLoad = (autoLoad == "true");
	this.alwaysShow = (alwaysShow == "true");
	this.alwaysShowScroller = (alwaysShowScroller == "true");
	// table属性
	this.border = border;
	this.styleClass = styleClass;
	this.headerClass = headerClass;
	this.rowClasses = rowClasses;
	this.columnClasses = columnClasses;
	this.rowOnClass = rowOnClass;	// 鼠标放上去时的当前行样式
	this.sortFields = ((sortFields != null && sortFields != "") ? sortFields : null) ;	// 格式如:field1,field2,field3(逗号隔开)
	this.sortField;					// 当前的排序字段
	this.asc;						// 是否是正序字段
	this.ascSrc = ascSrc;			// 正序图片地址
	this.descSrc = descSrc;			// 倒序图片地址
	this.displayJump = (displayJump == "true");	// 是否显示用于跳转的input
	this.strJump = strJump;						// 跳转按钮的label
	this.strRecordTotal = strRecordTotal;
	this.strPageTotal = strPageTotal;
	this.displayInfo = (displayInfo == "true");
	this.scrollerOn = scrollerOn;				// top or bottom, default bottom
	this.scrollerClass = scrollerClass;			// scroller样式
	this.scrollerInfoClass = scrollerInfoClass;
	this.scrollerPageClass = scrollerPageClass;
	this.scrollerPageCurrentClass = scrollerPageCurrentClass;
	this.scrollerPageOnClass = scrollerPageOnClass;
	this.tableObj;						// Q.F.UIMiniDataTable.Table
	
	// -------------------------------------------------------------------------------------------------
	this.editColumns = (editColumns.indexOf(",") != -1 ? editColumns.split(",") : new Array());		// format 1,1,0,0,1
	this.editListener = editListener;	// el expression string
	this.ajaxMode = "search";			// [search,editRow,editAll] 用于区分请求模式
	// -------------------------------------------------------------------------------------------------
	
	this.init = function() {
		var _self = this;
		if (this.refFull != null && this.refFull != "") {
			if (this.refFull.indexOf(",") != -1) {
				this.refArr = this.refFull.split(",");				
			} else {
				this.refArr = new Array();
				this.refArr[0] = this.refFull;
			}
		}
		if (this.forFull != null && this.forFull != "") {
			if (this.forFull.indexOf(",") != -1) {
				this.forArr = this.forFull.split(",");
			} else {
				this.forArr = new Array();
				this.forArr[0] = this.forFull;
			}
		}		
		// openButton可能会因为showOpenButton的设置而没有在客户端泻染，所以应该检测是否存在
		if (this.openButton) {
			Q.U.attachEvent(this.openButton, "onclick", function(){_self.displayInnerPanel()});
		}
		
		this.global = new Q.F.UIMiniDataTable.Global();
		this.global.start = 0;
		this.global.pageSize = parseInt(pageSize, 10);	// 必须转化为整数，否则在计算时会出问题
		this.global.displayPage = parseInt(displayPage, 10);
		this.global.img_min_first_src = Q.get(this.clientId + ":img_min_first").value;
		this.global.img_min_last_src = Q.get(this.clientId + ":img_min_last").value;
		this.global.img_min_next_src = Q.get(this.clientId + ":img_min_next").value;
		this.global.img_min_previous_src = Q.get(this.clientId + ":img_min_previous").value;
	
		// 自动载入数据，使用延迟，否则在IE下会出现错误提示
		if (this.autoLoad) {
			Q.U.setTimeout(_self.toSearch, 100, 0, _self);
		}
	}
	this.getTableObj = function() {
		return this.tableObj;
	}
	this.toSearch = function(start, miniDataTable) {	// start 起始记录
		var _self = null;
		if (miniDataTable != null) {
			_self = miniDataTable;
			Q.F.loading(true, miniDataTable.clientId); // 将loading图标定位到miniDataTable所在位置
		} else {
			_self = this;
			Q.F.loading(true);
		}
		var ajax = Q.F.Ajax.build(_self.clientId);
		_self.global.start = parseInt(start, 10);
		_self.ajaxMode = "search";
		ajax.put("componentClass", _self.componentClass);
		ajax.put("searchExp", _self.searchExp);
		ajax.put("ajaxMode", _self.ajaxMode);
		ajax.put("pageSize", _self.global.pageSize);
		ajax.put("start", _self.global.start);
		ajax.put("sortField", (_self.sortField ? _self.sortField : ""));
		ajax.put("asc", (_self.asc ? "true" : "false"));
		if (_self.refArr != null && _self.refArr != "") {
			for (var i = 0; i < _self.refArr.length; i++) {
				var refObj = Q.get(_self.refArr[i]);
				if (refObj == null) {
					alert("ref Object not found!");
				} else {
					ajax.put("refValue" + i, refObj.value);					
				}
			}
			ajax.put("refCount", _self.refArr.length);
		} else {
			ajax.put("refCount", 0);
		}
		var _process = function() {
			_self.process(_self);
		}
	    ajax.setProcess(_process);
	    ajax.get();
	}
	this.toSearchByPage = function(pageIndex) {
		var regx = /^[0-9]+$/;
		if (!regx.test(pageIndex)) {
			return;
		}
		var PI = parseInt(pageIndex, 10);
		var pageTotal = 0;
		if (this.global.total != null && this.global.pageSize != null && this.global.pageSize > 0) {
			pageTotal = Math.ceil(this.global.total / this.global.pageSize);			
		}
		if (PI < 1) PI = 1;
		if (PI > pageTotal) PI = pageTotal;
		var start = this.global.pageSize * (PI - 1);
		this.toSearch(start);
	}
	this.process = function(miniDataTable) {
		var dataArrs;		// 二维数组,作为contentPanel内的列表数据
		var scroller;		// 翻页组件
		var xmlResponse = Q.F.Ajax.find(miniDataTable.clientId).request.responseXML;
		miniDataTable.global.total = Q.F.UIMiniDataTable.Parse.parseToTotal(xmlResponse); 	// 计算总数
		dataArrs = Q.F.UIMiniDataTable.Parse.parseToDataArrs(xmlResponse);					// 分析数据
		while (miniDataTable.contentPanel.hasChildNodes()) {
			miniDataTable.contentPanel.removeChild(miniDataTable.contentPanel.firstChild);
		}
		while (miniDataTable.scrollerPanelTop.hasChildNodes()) {
			miniDataTable.scrollerPanelTop.removeChild(miniDataTable.scrollerPanelTop.firstChild);
		}
		while (miniDataTable.scrollerPanelBottom.hasChildNodes()) {
			miniDataTable.scrollerPanelBottom.removeChild(miniDataTable.scrollerPanelBottom.firstChild);
		}
		// Render content
		if (dataArrs != null) {
			miniDataTable.tableObj = new Q.F.UIMiniDataTable.Table(miniDataTable, dataArrs);
			miniDataTable.contentPanel.appendChild(miniDataTable.tableObj.getElement());
		} else {
			miniDataTable.contentPanel.innerHTML = "";
		}
		// Render scroller
		if (miniDataTable.alwaysShowScroller || miniDataTable.global.total > miniDataTable.global.pageSize) {
			if (miniDataTable.scrollerOn == "both") {
				miniDataTable.scrollerPanelTop.appendChild(new Q.F.UIMiniDataTable.Scroller(miniDataTable).getScroller());
				miniDataTable.scrollerPanelBottom.appendChild(new Q.F.UIMiniDataTable.Scroller(miniDataTable).getScroller());
			} else if (miniDataTable.scrollerOn == "top"){
				miniDataTable.scrollerPanelTop.appendChild(new Q.F.UIMiniDataTable.Scroller(miniDataTable).getScroller());
			} else {
				miniDataTable.scrollerPanelBottom.appendChild(new Q.F.UIMiniDataTable.Scroller(miniDataTable).getScroller());
			}			
		}
		// Reset width,
		if (miniDataTable.tableObj != null && miniDataTable.tableObj.getElement() != null) {
			var innerTable = miniDataTable.tableObj.getElement();
			innerTable.style.width = miniDataTable.contentPanel.offsetWidth + "px";
		}
		Q.F.loading(false);
	}
	this.onSelectRowObj = function(rowIndex) {
		var dataController = this.tableObj.getDataController();
		if (this.forArr != null && this.forArr.length > 0) {
			for (var i = 0; i < this.forArr.length; i++) {
				var forObj = Q.get(this.forArr[i]);
				var dataField = dataController.getField(rowIndex, i);
				if (forObj != null && dataField != null) {
					forObj.value = dataField.getValue();
				}
			}
		}
		// 在“总是显示”的情况下无须display...
		if (!this.alwaysShow) {
			if (this.autoClose) {
				this.displayInnerPanel();
			}
		}
	}
	this.displayInnerPanel = function() {
		if (this.innerPanel.style.display == "none") {
			this.innerPanel.style.zIndex = Q.U.zIndex++;
			Q.U.toShow(this.innerPanel, 0.5);
			if (this.searchWhenOpen) {
				// 20100408 注释掉下面这句，这保证以后每次打开时都进行ajax请求。(因为有时候改变了miniDataTable所引用的外部控件的值，那么重新打开时应该reload)
				// this.searchWhenOpen = false;
				this.toSearch(0);
			}
		} else {
			Q.U.toHidden(this.innerPanel, 0.5);
		}
	}
	this.sortEvent = function(sortField) {
		if (this.sortField == null) {
			this.sortField = sortField;
			this.asc = true;
		} else {
			if (this.sortField == sortField) {
				this.asc = !this.asc;
			} else {
				this.sortField = sortField;
				this.asc = true;
			}
		}
		this.toSearch(0);
	}
	this.toUpdateRow = function(rowIndex, columnIndex) {
		var _self = this;
		var rowFields = _self.getTableObj().getDataController().getFields(rowIndex);
		var field = _self.getTableObj().getDataController().getField(rowIndex, columnIndex); // Q.F.UIMiniDataTable.Field
		if (rowFields == null || rowFields.length <= 0) 
			return;
		
		_self.ajaxMode = "editRow";
		Q.F.loading(true, field.getElement()); // 将loading图标定位到miniDataTable所在位置
		var ajax = Q.F.Ajax.build(_self.clientId);
		
		ajax.put("componentClass", _self.componentClass);
		ajax.put("editListenerExp", _self.editListener);
		ajax.put("ajaxMode", _self.ajaxMode);
		ajax.put("rowIndex", rowIndex);
		ajax.put("columnCount", rowFields.length);
		for (var i = 0; i < rowFields.length; i++) {
			ajax.put("value_" + rowIndex + "_" + i, rowFields[i].getValue());	// format e.g. "value_0_1"
		}
		var _process = function() {
			var result = ajax.request.responseText;
			if (result != null && result != "")
				alert(result);
			Q.F.loading(false);
		}
	    ajax.setProcess(_process);
	    ajax.get();
	}
//	this.toUpdateAll = function() {
//		
//	}
	this.getEditColumns = function() {return this.editColumns}
	this.isEnabledEdit = function() {
		return (this.editListener != null && this.editListener != "");
	}
	this.init(); // 初始化
}

Q.F.UIMiniDataTable.Scroller = function(miniDataTable) {
	this.miniDataTable = miniDataTable;
	this.global = miniDataTable.global;
	this.scroller;
	this.contentRow;	// scroller row(第一行)
	this.cellCount = 0;	// 列数
	this.jumpInput;
	this.jumpButton;
	
	this.pageTotal;		// 总页数
	this.pageCurrent;	// 当前页
	this.pageObjArr; 	// 需要显示的页数组
	
	this.init = function() {
		this.scroller = document.createElement("table");
		this.contentRow = this.scroller.insertRow(0);
		this.calculatePageTotal();
		this.calculatePageObj();
		this.calculatePageCurrent();
		
		var start_first = 0;
		var start_previous;
		var start_next;
		var start_last = (this.pageTotal - 1) * this.global.pageSize;
		var jsEventPrevious = true;
		var jsEventNext = true;
		if (this.pageCurrent == 0) {
			start_previous = 0;
			jsEventPrevious = false;	// 当前页为第一页，则不需要响应向前翻页
		} else {
			start_previous = (this.pageCurrent - 1) * this.global.pageSize;
		}
		if (this.pageCurrent >= this.pageTotal - 1) {
			start_next = (this.pageTotal - 1) * this.global.pageSize;
			jsEventNext = false;		// 当前页为最后页，同样不需要响应向后翻页
		} else {
			start_next = (this.pageCurrent + 1) * this.global.pageSize;
		}
		this.getCell().appendChild(this.encodeImg(this.miniDataTable.clientId, this.global.img_min_first_src, start_first, jsEventPrevious));
		this.getCell().appendChild(this.encodeImg(this.miniDataTable.clientId, this.global.img_min_previous_src, start_previous, jsEventPrevious));
		for (var i = 0; i < this.pageObjArr.length; i++) {
			this.getCell().appendChild(this.encodePageObj(this.miniDataTable.clientId, this.pageObjArr[i], this.miniDataTable));
		}
		this.getCell().appendChild(this.encodeImg(this.miniDataTable.clientId, this.global.img_min_next_src, start_next, jsEventNext));
		this.getCell().appendChild(this.encodeImg(this.miniDataTable.clientId, this.global.img_min_last_src, start_last, jsEventNext));
		if (this.miniDataTable.displayInfo) {
			this.getCell().appendChild(this.encodeInfo(this.miniDataTable.strRecordTotal + "" + this.global.total, "Total Records", this.miniDataTable.scrollerInfoClass));
			this.getCell().appendChild(this.encodeInfo(this.miniDataTable.strPageTotal + "" + this.pageTotal, "Page Count", this.miniDataTable.scrollerInfoClass));			
		}
		if (this.miniDataTable.displayJump) {
			this.getCell().appendChild(this.encodeJumpObj(this.miniDataTable.clientId, this.pageCurrent + 1, this.miniDataTable.strJump));
		}
		this.scroller.style.textAlign = "center";
		this.scroller.style.padding = this.scroller.style.margin = "0";
		this.scroller.cellSpacing = "1";
		this.scroller.cellPadding = "0";
		this.scroller.className = this.miniDataTable.scrollerClass;
	}
	this.getCell = function() {
		var cell = this.contentRow.insertCell(this.cellCount++);
		cell.width = "18";
		return cell;
	}
	this.encodeJumpObj = function(clientId, pageCurrent, buttonStr) {
		var obj = document.createElement("table");
		var row0 = obj.insertRow(0);
		this.jumpInput = document.createElement("input");
		this.jumpButton = document.createElement("input");
		this.jumpInput.setAttribute("type", "text");
		this.jumpInput.setAttribute("value", pageCurrent);
		this.jumpInput.style.width = "30px";
		this.jumpInput.style.textAlign = "center";
		this.jumpInput.onkeydown = function() {
			var event = Q.U.getEvent();
			if (event.keyCode == 13) {
				Q.F.UIMiniDataTable.toSearchByPage(clientId, this.value);
			}
		}
		this.jumpButton.setAttribute("type", "button");
		this.jumpButton.setAttribute("value", buttonStr);
		this.jumpButton.refInput = this.jumpInput;
		this.jumpButton.onclick = function() {
			Q.F.UIMiniDataTable.toSearchByPage(clientId, this.refInput.value);
		}
		row0.insertCell(0).appendChild(this.jumpInput);
		row0.insertCell(1).appendChild(this.jumpButton);
		obj.style.padding = obj.style.margin = obj.border = obj.cellSpacing = obj.cellPadding = "0";
		this.jumpButton.style.marginBottom = "1px";
		return obj;
	}
	this.encodeInfo = function(info, tip, className) {
		var div = document.createElement("div");
		div.innerHTML = info;
		div.setAttribute("title", tip);
		div.className = className;
		return div;
	}
	this.encodePageObj = function(clientId, pageObj, miniDataTable) {
		var div = document.createElement("div");
		div.innerHTML = (pageObj.label + 1);
		div.className = miniDataTable.scrollerPageClass;
		if (this.pageCurrent == pageObj.label) {
			div.className = miniDataTable.scrollerPageCurrentClass;
		} else {
			Q.U.attachEvent(div, "onmousedown", function() {
				Q.F.UIMiniDataTable.toSearch(clientId, pageObj.start);
			});
			div.onmouseover = function() {
				this.className = miniDataTable.scrollerPageOnClass;
			}
			div.onmouseout = function() {
				this.className = miniDataTable.scrollerPageClass;
			}
		}
		return div;
	}
	// start -> 起始记录, jsEvent -> true/false 是否
	this.encodeImg = function(clientId, src, start, jsEvent) {
		var div = document.createElement("div");
		var img = document.createElement("img");
		img.setAttribute("src", src);
		div.appendChild(img);
		if (jsEvent) {
			Q.U.attachEvent(div, "onmousedown", function() {
				Q.F.UIMiniDataTable.toSearch(clientId, start);
			});
			div.onmouseover = function() {
				this.style.cursor = "pointer";
			}
		}
		div.style.cssText = "border:0px solid green;margin:0;padding:0;";
		return div;
	}
	this.calculatePageTotal = function() {
		this.pageTotal = Math.ceil(this.global.total / this.global.pageSize);
	}
	this.calculatePageObj = function () {
		this.pageObjArr = new Array();
		var startPage = 0;
		var totalToDisplay = 0;
		var recordStartDisplay = 0;	// 起始记录
		var leavePage;				// 剩下的页数
		var center = Math.floor(this.global.displayPage / 2);  // 取中点
		if (this.pageTotal <= this.global.displayPage) {
			recordStartDisplay = 0;
			totalToDisplay = this.pageTotal;
		} else {
			recordStartDisplay = this.global.start - center * this.global.pageSize;
			if (recordStartDisplay < 0) {
				recordStartDisplay = 0;
			}
			startPage = recordStartDisplay / this.global.pageSize;
			var theEnd = startPage + this.global.displayPage;
			if (theEnd > this.pageTotal) { // 如果后面的页数不足以显示global.displayPage数目的记录
				var offset = theEnd - this.pageTotal;
				recordStartDisplay -= offset * this.global.pageSize; // 则再次前移
				if (recordStartDisplay < 0) {
					recordStartDisplay = 0;
				}
			}
		}
		startPage = recordStartDisplay / this.global.pageSize;	// 重新计算起始页
		leavePage = this.pageTotal - startPage;		// 计算出剩下的页数
		totalToDisplay = this.global.displayPage <= leavePage ? this.global.displayPage : leavePage;
		for (var i = 0; i < totalToDisplay; i++) {
			var pageObj = new Q.F.UIMiniDataTable.PageObj();
			pageObj.label = startPage + i;
			pageObj.start = recordStartDisplay + i * this.global.pageSize;
			this.pageObjArr[i] = pageObj;
		}
	}
	this.calculatePageCurrent = function() {
		this.pageCurrent = this.global.start / this.global.pageSize;
	}
	this.getScroller = function() {
		return this.scroller;
	}
	this.init();
}
Q.F.UIMiniDataTable.PageObj = function() {
	this.label;	// 页码
	this.start;	// 该页的起始记录
}
Q.F.UIMiniDataTable.Global = function() {
	this.total;
	this.start;
	this.pageSize;
	this.displayPage;
	this.img_min_first_src;	// 几个翻页图片的src
	this.img_min_last_src;
	this.img_min_next_src;
	this.img_min_previous_src;
}
Q.F.UIMiniDataTable.Table = function(miniDataTable, dataArrs) {
	this.dataController = new Q.F.UIMiniDataTable.DataController(miniDataTable, dataArrs);
	this.miniDataTable = miniDataTable;
//	this.dataArrs = dataArrs;	// 二维数据
	this.rowObjArr;
	this.table;
	this.enabledRowEvent = (miniDataTable.forArr != null && miniDataTable.forArr.length > 0); // 只有for属性存在的情况下才设置table行的鼠标响应
	this.init = function() {
		this.table = document.createElement("table");
		this.rowObjArr = this.createTableAsRowObj(this.table, this.dataController.getRowCount(), this.dataController.getColumnCount());
		for (var i = 0; i < this.rowObjArr.length; i++) {
			var rowObj = this.rowObjArr[i];
			var columnArr = rowObj.columns;
			if (this.enabledRowEvent) {
				this.setRowEvent(this.miniDataTable, rowObj, i);
			}
			for (var n = 0; n < columnArr.length; n++) {
				var column = columnArr[n];
				column.appendChild(this.dataController.getField(i, n).getElement());
			}
		}
		this.table.border = this.miniDataTable.border;
		this.table.className = this.miniDataTable.styleClass;
		this.encodeHeaders();	// table header
		this.setRowStyle(this.miniDataTable, this.rowObjArr); // table rows and columns
	}
	this.encodeHeaders = function() {
		var titles, header, sortFields;
		var miniDataTable = this.miniDataTable;
		if (this.miniDataTable.strHeaders != null) {
			// 渲染标题
			titles = this.miniDataTable.strHeaders.split(",");
			if (titles == null || titles.length <= 0) return;
			
			// 排序标题
			if (this.miniDataTable.sortFields != null) {
				sortFields = this.miniDataTable.sortFields.split(",");
			}
			
			header = this.table.insertRow(0);
			for (var i = 0; i < titles.length; i++) {
				var column = header.insertCell(i);
				var htmlHeader = document.createElement("a");
				htmlHeader.innerHTML = titles[i];
				column.appendChild(htmlHeader);
				// set sort event
				if (sortFields != null && sortFields.length > i) {
					htmlHeader.sortField = sortFields[i];
					if (htmlHeader.sortField != null && htmlHeader.sortField != "") {
						htmlHeader.onclick = function() {
							miniDataTable.sortEvent(this.sortField);
						}
						htmlHeader.style.cursor = "pointer";
						if (htmlHeader.sortField == miniDataTable.sortField) {
							var flag = document.createElement("img");
							if (miniDataTable.asc == true) {
								flag.setAttribute("src", miniDataTable.ascSrc);
							} else {
								flag.setAttribute("src", miniDataTable.descSrc);
							}
							flag.style.verticalAlign = "middle";
							htmlHeader.appendChild(flag);
						}
					}
				}
			}
			header.className = this.miniDataTable.headerClass;
		}
	}
	this.setRowEvent = function(miniDataTable, rowObj, rowIndex) {
		rowObj.row.onmousedown = function() {
			miniDataTable.onSelectRowObj(rowIndex);
		}
		rowObj.row.style.cursor = "pointer";
	}
	this.setRowStyle = function(miniDataTable, rowObjArr) {
		if (rowObjArr == null || rowObjArr.length <= 0) return;
		var rowClasses = miniDataTable.rowClasses.split(",");
		var columnClasses = miniDataTable.columnClasses.split(",");
		for (var i = 0, x = 0; i < rowObjArr.length; i++, x++) {
			if (x >= rowClasses.length) {
				x = 0;
			}
			var rowObj = rowObjArr[i];
			rowObj.row.className = rowClasses[x];
			rowObj.row.classNameOut = rowClasses[x];	// 添加额外属性，记住鼠标out时的样式
			if (miniDataTable.rowOnClass != null && miniDataTable.rowOnClass != "") {
				rowObj.row.onmouseover = function() {
					this.className = miniDataTable.rowOnClass;
				}
				rowObj.row.onmouseout = function() {
					this.className = this.classNameOut;
				}
			}
			var columns = rowObj.columns;
			for (var n = 0, y = 0; n < columns.length; n++, y++) {
				if (y >= columnClasses.length) {
					y = 0;
				}
				var column = columns[n];
				column.className = columnClasses[y];
			}
		}
	}
	this.getElement = function() {
		return this.table;
	}
	this.getDataController = function() {
		return this.dataController;
	}
	this.createTableAsRowObj = function (table, rows, columns) {
		var rowObjArr = new Array();
		for (var i = 0; i < rows; i++) {
			var rowObj = new RowObj();
			rowObjArr[i] = rowObj;
			rowObj.row = table.insertRow(i);
			for (var n = 0; n < columns; n++) {
				rowObj.columns[n] = rowObj.row.insertCell(n);
			}
		}
		function RowObj() {
			this.row = null;
			this.columns = new Array();	// 行内的所有列
		}
		return rowObjArr;
	}
	this.init();
}
Q.F.UIMiniDataTable.DataController = function(miniDataTable, dataArrs) {
	this.rows = 0;
	this.columns = 0;
	this.dataWrap; // 二维数组,include Fields
	this.editor = new Q.F.UIMiniDataTable.Editor(miniDataTable);
	this.init = function() {
		if (dataArrs != null && dataArrs.length > 0) {
			this.rows = dataArrs.length;
			this.columns = dataArrs[0].length;
			this.dataWrap = new Array(this.rows);
			for (var i = 0; i < this.rows; i++) {
				this.dataWrap[i] = new Array(this.columns);
				for (var n = 0; n < this.columns; n++) {
					this.dataWrap[i][n] = new Q.F.UIMiniDataTable.Field(dataArrs[i][n], this.editor, i, n);
				}
			}
		}
	}
	this.getRowCount = function() {
		return this.rows;
	}
	this.getColumnCount = function() {
		return this.columns;
	}
	this.getDataWrap = function() {
		return this.dataWrap;
	}
	this.getField = function(rowIndex, columnIndex) {
		if (rowIndex >= this.rows || columnIndex >= this.columns) 
			return null;
		return this.dataWrap[rowIndex][columnIndex];
	}
	this.getFields = function(rowIndex) {
		if (rowIndex >= this.rows) 
			return null;
		var fields = new Array(this.columns);
		for (var c = 0; c < this.columns; c++) {
			fields[c] = this.getField(rowIndex, c);
		}
		return fields;
	}
	this.isEmpty = function() {
		return (this.rows == null || this.rows == 0)
	}
	this.init();
}
Q.F.UIMiniDataTable.Field = function(value, editor, rowIndex, columnIndex) {
	this.element = document.createElement("div"); // element include label
	this.label = document.createElement("div");
	this.editor = editor;		// Q.F.UIMiniDataTable.Editor();
	this.rowIndex = rowIndex;	// 当前field的table坐标
	this.columnIndex = columnIndex;
	this.init = function() {
		this.element.appendChild(this.label);
		this.label.innerHTML = value;
		var _editor = this.editor;
		var _field = this;
		this.label.style.minHeight = "20px"; // Fix bug, 最少高度，避免在空数据时，高度变为0而点击不到
		Q.U.attachEvent(this.label, "ondblclick", function(){_editor.setEditField(_field)});
	}
	this.getValue = function() {
		return this.label.innerHTML;
	}
	this.setValue = function(value) {
		this.label.innerHTML = value;
	}
	this.hideLabel = function() {
		this.label.style.display = "none";
	}
	this.showLabel = function() {
		this.label.style.display = "block";
	}
	this.getElement = function() {
		return this.element;
	}
	this.getRowIndex = function() {
		return this.rowIndex;
	}
	this.getColumnIndex = function() {
		return this.columnIndex;
	}
	this.init();
}
Q.F.UIMiniDataTable.Editor = function(miniDataTable) {
	this.miniDataTable = miniDataTable;
	this.input; // 编辑field
	this.field;	// 关联的Field (Q.F.UIMiniDataTable.Field)
	this.init = function() {
		this.input = document.createElement("input");
		this.input.setAttribute("type", "text");
		this.input.style.width = "100%";
		var _editor = this;
		Q.U.attachEvent(this.input, "onblur", function(){_editor.apply()});
		Q.U.attachEvent(this.input, "onkeydown", function(){_editor.applyByKeyPress()});
	}
	this.setEditField = function(field) { // 设置并关联到一个field
		if (!this.isEditable(field.getColumnIndex())) {
			return;
		}
		this.field = field;
		this.input.value = this.field.getValue();
		this.field.hideLabel();
		this.field.getElement().appendChild(this.input);
		this.input.style.display = "block";
		this.input.focus();
	}
	this.applyByKeyPress = function() {
		var event = Q.U.getEvent();
		if (event != null && event.keyCode == 13)
			this.apply();
	}
	this.apply = function() {	// 完成编辑，并应用value
		if (this.input.style.display == "none") // Fix bug, double update by Keypress and blur
			return;
		if (this.field.getValue() == this.input.value) {
			this.input.value = "";
			this.input.style.display = "none";
			this.field.showLabel();
			return; // No change
		}
		this.field.setValue(this.input.value);
		this.field.showLabel();
		this.input.value = "";
		this.input.style.display = "none";
		this.miniDataTable.toUpdateRow(this.field.getRowIndex(), this.field.getColumnIndex()); // 更新数据
	}
	this.isEditable = function(columnIndex) {
		if (this.miniDataTable.isEnabledEdit()) { // 在绑定了editListener之后默认开启所有field的edit功能, 通过editColumns控制非editable列
			var editColumns = this.miniDataTable.getEditColumns();
			if (editColumns != null && columnIndex < editColumns.length) {
				return (editColumns[columnIndex] != "0");
			}
			return true;
		}
		return false;
	}
	this.init();
}